package com.sunyzc.ebaotech.ybt.simulator.icbc;

import java.io.ObjectInputStream;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;

import com.sunyzc.ebaotech.ybt.simulator.AbstractProcessor;
import com.sunyzc.ebaotech.ybt.simulator.util.IOUtil;

/**
 * 1012 - 新单试算(104) <br>
 * 1013 - 新单缴费(102) <br>
 * 801 - 日结对账(801)(注意实际是没有对账请求的交易的) <br>
 */
public class ICBCProcessor extends AbstractProcessor {
	private final static int HEAD_LENGTH = 16;
	private final static int BODY_LENGTH_BEGIN_INDEX = 0;
	private final static int BODY_LENGTH_END_INDEX = 6;
	private final static int SERVER_PORT = 8102;
	private final static String TRANS_ENDCODING = "GBK";
	private final static String CIPHER_ALGORITHM = "DES";
	private final static SecretKey SECRET_KEY = readSecretKey(); // new SecretKeySpec("dbanudbh".getBytes(), "DES");

	@Override
	public byte[] generateHeadBytes(String transType, byte[] bodyContent) throws Exception {
		String contentLength = (bodyContent == null ? 0 : bodyContent.length) + "";
		while (contentLength.length() < 6)
			contentLength += " ";
		String requestHeadContent = contentLength + transType + "000   ";
		return requestHeadContent.getBytes(TRANS_ENDCODING);
	}

	public static void main(String[] args) {
		try {
			String bodyContentStr = "123456中文";
			System.out.println(new String(bodyContentStr.getBytes("GBK"), "GBK"));
			System.out.println(new String(bodyContentStr.getBytes("ISO-8859-1"), "ISO-8859-1"));
			System.out.println(new String(bodyContentStr.getBytes()));

			Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
			cipher.init(Cipher.ENCRYPT_MODE, SECRET_KEY);
			byte[] encryptedBytes = cipher.doFinal(bodyContentStr.getBytes("GBK"));
			System.out.println(new String(encryptedBytes, "GBK"));

			// encryptedBytes = new String(encryptedBytes, "ISO-8859-1").getBytes("ISO-8859-1"); // OK
			encryptedBytes = new String(encryptedBytes, "GBK").getBytes("GBK"); // TODO 加密后的byte数组不能强制转换成字符串，也就是说字符串和byte数组在这种情况下不是互逆的
			// encryptedBytes = new String(encryptedBytes).getBytes(); // TODO

			cipher.init(Cipher.DECRYPT_MODE, SECRET_KEY);
			byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
			System.out.println(new String(decryptedBytes, "GBK"));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	protected byte[] beforeSend(String bodyContentStr) throws Exception {
		return encrypt(bodyContentStr.getBytes(TRANS_ENDCODING));
	}

	@Override
	protected byte[] afterReceived(byte[] bodyContentBytes) throws Exception {
		return decrypt(bodyContentBytes);
	}

	@Override
	public int getServerPort() {
		return SERVER_PORT;
	}

	@Override
	public String getTransEncoding() {
		return TRANS_ENDCODING;
	}

	/** ICBC交易报文的时间格式是yyyy-MM-dd HH:mm:ss，而日结对账的日期格式是yyyyMMdd HHmmss */
	@Override
	protected String[] getDateFormatStr(String transType) {
		if ("8001".equals(transType) || "801".equals(transType))
			return new String[] { "yyyyMMddHHmmss", "yyyyMMdd", "HHmmss" };
		else
			return new String[] { "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd", "HH:mm:ss" };
	}

	@Override
	protected int getHeadLength() {
		return HEAD_LENGTH;
	}

	@Override
	protected int getBodyLengthBeginIndex() {
		return BODY_LENGTH_BEGIN_INDEX;
	}

	@Override
	protected int getBodyLengthEndIndex() {
		return BODY_LENGTH_END_INDEX;
	}

	private static SecretKey readSecretKey() {
		SecretKey SECRET_KEY = null;
		ObjectInputStream inputStream = null;
		try {
			inputStream = new ObjectInputStream(ICBCProcessor.class.getResourceAsStream("DesKey.des"));
			SECRET_KEY = (SecretKey) inputStream.readObject();
			System.out.println("密钥: " + new String(SECRET_KEY.getEncoded()));
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			IOUtil.closeQuietly(inputStream);
		}
		return SECRET_KEY;
	}

	private static byte[] encrypt(byte[] originalContent) throws Exception {
		Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
		cipher.init(Cipher.ENCRYPT_MODE, SECRET_KEY);
		byte[] encryptedBytes = cipher.doFinal(originalContent);
		return encryptedBytes;
	}

	private static byte[] decrypt(byte[] encryptedContent) throws Exception {
		Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
		cipher.init(Cipher.DECRYPT_MODE, SECRET_KEY);
		byte[] decryptedBytes = cipher.doFinal(encryptedContent);
		return decryptedBytes;
	}
}
